// FrogiCALC (Express) Square
#ifdef sm
struct {
	uint32_t a[2];
	uint8_t op;
	unsigned keep : 1;
} cs;
#else
void draw_line(bit which) {
	uint8_t i;
	uint32_t t = sm.cs.a[which];
	for (i = 0; i < 9; i++) {
		draw_char((8 - i) * 6 + 16, (uint8_t) which * 12, '0' + t % 10);
		t /= 10;
	}
}

void draw_op(void) {
	char c;
	switch (sm.cs.op) {
	case 0:
		c = '+';
		break;
	case 1:
		c = '-';
		break;
	case 2:
		c = 0xd7;
		break;
	case 3:
		c = 0xf7;
		break;
	}
	draw_char(0, 12, c);
}

void calculate(void) {
	switch (sm.cs.op) {
	case 0:
		sm.cs.a[0] += sm.cs.a[1];
		break;
	case 1:
		sm.cs.a[0] -= sm.cs.a[1];
		break;
	case 2:
		sm.cs.a[0] *= sm.cs.a[1];
		break;
	case 3:
		if (sm.cs.a[1]) {
			uint32_t t;
			t = sm.cs.a[0] % sm.cs.a[1];
			sm.cs.a[0] /= sm.cs.a[1];
			sm.cs.a[1] = t;
			draw_line(0);
			draw_line(1);
		}
		return;
	}
	draw_line(0);
	if (!sm.cs.keep) {
		sm.cs.a[1] = 0;
		draw_line(1);
	}
}

void cs_on_keydown(uint8_t key) {
	switch (key) {
	case 5:
		sm.cs.a[0] = 0;
		draw_line(0);
		sm.cs.op = 0;
		draw_op();
	case 6:
		sm.cs.a[1] = 0;
		draw_line(1);
		break;
	case 9:
		sm.cs.a[1] *= sm.cs.a[1];
		draw_line(1);
		break;
	case 10: case 11: case 12:
		key += 8;
	case 15: case 16: case 17:
		key += 8;
	case 20: case 21: case 22:
		key -= 19;
		sm.cs.a[1] *= 10;
		sm.cs.a[1] += key;
		draw_line(1);
		break;
	case 13:
		sm.cs.a[0] ^= sm.cs.a[1];
		sm.cs.a[1] ^= sm.cs.a[0];
		sm.cs.a[0] ^= sm.cs.a[1];
		draw_line(0);
		draw_line(1);
		break;
	case 14:
		sm.cs.a[0] = sm.cs.a[1];
		sm.cs.a[1] = 0;
		draw_line(0);
		draw_line(1);
		break;
	case 18:
		sm.cs.a[1] /= 10;
		draw_line(1);
		break;
	case 19:
		sm.cs.keep = !sm.cs.keep;
		led_inv = !led_inv;
		break;
	case 23:
		sm.cs.op = 0;
		draw_op();
		break;
	case 24:
		sm.cs.op = 1;
		draw_op();
		break;
	case 28:
		sm.cs.op = 2;
		draw_op();
		break;
	case 29:
		sm.cs.op = 3;
		draw_op();
		break;
	case 26:
		sm.cs.a[1] *= 10;
	case 25:
		sm.cs.a[1] *= 10;
		draw_line(1);
		break;
	case 27:
		calculate();
		break;
	}
	lcd_flush();
}

void cs_on_init(void) {
	lcd_clear_button_text();
	lcd_set_button_text(5, L"AC");
	lcd_set_button_text(6, L"CE");
	lcd_set_button_text(9, L"x\xb2");
	lcd_set_button_text(13, L"\u21c5");
	lcd_set_button_text(14, L"\u2191");
	lcd_set_button_text(18, L"\u232b");
	lcd_set_button_text(19, L"K");
	lcd_set_button_text(23, L"+");
	lcd_set_button_text(24, L"\u2212");
	lcd_set_button_text(28, L"\xd7");
	lcd_set_button_text(29, L"\xf7");
	lcd_set_button_text(27, L"=");
	lcd_set_button_text(26, L"00");
	lcd_set_button_text(25, L"0");
	lcd_set_button_text(20, L"1");
	lcd_set_button_text(21, L"2");
	lcd_set_button_text(22, L"3");
	lcd_set_button_text(15, L"4");
	lcd_set_button_text(16, L"5");
	lcd_set_button_text(17, L"6");
	lcd_set_button_text(10, L"7");
	lcd_set_button_text(11, L"8");
	lcd_set_button_text(12, L"9");
	sm.cs.a[0] = sm.cs.a[1] = sm.cs.op = sm.cs.keep = 0;
	lcd_clear();
	draw_line(0);
	draw_line(1);
	draw_op();
	led_inv = 1;
	on_keydown = cs_on_keydown;
	lcd_flush();
}
#endif
